# This file is a part of Conspire
# $Id: models.py 66 2007-05-02 16:43:06Z meyarivan $

from django.db import models
from django.contrib.auth.models import User
from django.db import transaction
from django.conf import settings

import datetime
import os.path
from md5 import md5 as hashfunc

from freedel.contentstore.models import *
from freedel.contentstore import add_content, update_content

LEVELS = (('BEG','Beginner'),
          ('INT','Intermediate'),
          ('ADV','Advanced'))

class Category(models.Model):
    name = models.CharField(verbose_name = "title", maxlength = 50)
    description = models.TextField(verbose_name = "description", maxlength = 200)

    def __str__(self):
        return self.name
    
    class Admin: pass

    class Meta:
        verbose_name_plural = "Categories"


class PresentationFiles(models.Model):
    """
    """

    name = models.CharField(maxlength = 255)
    content_info = models.ForeignKey(VersionedContentInfo)
    chosen_version = models.ForeignKey(VersionedContentStore)

    def __str__(self):
        return self.name
    
    class Admin:
        pass

    class Meta:
        verbose_name_plural = 'Presentation files'

        
class Talk(models.Model):
    talk_name = models.CharField(verbose_name = "title", maxlength = 255)
    abstract = models.TextField(verbose_name = "summary")
    presentation_file = models.ForeignKey(PresentationFiles)
    talk_status = models.BooleanField(verbose_name = "talk status") # True if selected
    category = models.ForeignKey(Category, verbose_name = "category")
    equipment = models.BooleanField(verbose_name = "equipment needed")
    level = models.CharField(verbose_name = "audience", maxlength = 50, choices = LEVELS)
    comments = models.TextField(verbose_name = "comments")

    # to be added by the admin
    nick = models.CharField (verbose_name = "codename", maxlength = 50, default = "None")
    duration = models.FloatField (verbose_name = "duration (hours)", default = 0.0,
                                  max_digits = 3, decimal_places = 2)

    def __str__(self):
        if self.nick != "None":
            return self.nick
        return self.talk_name
    
    class Admin: pass

    @transaction.commit_on_success
    def add_presentation_file(self, content, autoset = False):
        """
        """

        # TODO
        # 1. content type ?
        # 2. name of the file/content ?

        try:
            ci = self.presentation_file.content_info
            
            update_content(ci, content)

            if autoset is True:
                latest_version = ci.get_version()
                self.presentation_file.chosen_version = latest_version

            self.presentation_file.save()
            
        except PresentationFiles.DoesNotExist:
            pf = PresentationFiles()
            pf.content_info = add_content(content)
            pf.chosen_version = pf.content_info.get_version()
            pf.save()

            self.presentation_file = pf

    def set_presentation(self, version = -1):
        pass
    

class UserProfileManager(models.Manager):

    @transaction.commit_on_success
    def create_user_profile(self, data):
        """ Create a UserProfile instance and save it.

            The data passed as the only argument is typically the cleaned up
            data from a form submission.

            Returns an instance of UserProfile

        """

        # create a user object

        user = User.objects.create_user(data['username'],
                                        data['email'],
                                        data['password1'])

        user.is_active = False
        user.save()
        
        # create a user profile object

        up = UserProfile()
        up.user = user
        up.affiliation = data['affiliation']
        up.location = data['location']
        up.accomodation = data['accomodation']
##         up.accomodation_info = data['accomodation_info']
        up.travel_assistance = data['travel_assistance']
        up.travel_info = data['travel_info']
        up.personal_url = data['personal_url']
        up.comments = data['comments']
        up.activation_key = up.make_activation_key()
        up.key_expires = datetime.datetime.now()# + datetime.timedelta(2)
        up.save()

        for t in data['tracks']:
            cat = Category.objects.get(name = t)
            up.tracks_of_interest.add(cat)

        # save the photograph

        if data['photograph'] is not None:
            up.save_mugshot(data['photograph']['content'])

        # activation mail is sent using a cron job
        
        return up


class UserProfile(models.Model):
    activation_key = models.CharField (verbose_name = "activation key", maxlength = 40)
    key_expires = models.DateTimeField(verbose_name = "activation key expiry date") 
    user = models.ForeignKey(User, unique = True, verbose_name = "related user")
    affiliation = models.CharField(verbose_name = "affiliated to", maxlength = 100)
    location = models.CharField(verbose_name = "location", maxlength = 50)
    accomodation = models.BooleanField(verbose_name = "require accomodation")
    accomodation_info = models.TextField(verbose_name = "accomodation details")
    travel_assistance = models.BooleanField(verbose_name = "require travel assistance")
    travel_info = models.TextField(verbose_name = "travel information")
    personal_url = models.URLField(verbose_name = "URL to personal website")
    tracks_of_interest = models.ManyToManyField(Category, verbose_name = "tracks of interest")
    comments = models.TextField (verbose_name = "misc information (other preferences etc)", maxlength = 500)
    photograph = models.TextField(blank = True)
    bio = models.TextField(blank = True, null = True)
    

    objects = UserProfileManager()

    def get_full_name(self):
        """ Return full name of the user.
        
        """

        return self.user.get_full_name()
    
    def make_activation_key(self):
        """ Return an activation key suitable for sending via plain-text mail.

            Returns an ascii string.

        """

        return 'X' * 40

    def reset_expiry_datetime(self, new_datetime = None):
        """
        """

        if new_datetime is None:
            new_datetime = datetime.datetime.now() + datetime.timedelta(2)
        
        self.key_expires = new_datetime
        self.save()
        
    def activation_key_expired(self, key):
        """Checks if the activation key has expired beyond the specified amount
        of Activation days"""
        current_time = datetime.datetime.today()
        if current_time - key_expires > settings.ACCOUNT_ACTIVATION_DAYS:
            return True
        return False                

    def __str__(self):
        fn = self.user.get_full_name()
        if not fn:
            return self.user.username
        return fn

    class Admin: pass

    def save_mugshot(self, img_data):
        """
        """

        basepath = settings.MEDIA_ROOT
        destfile =  hashfunc(img_data).hexdigest()
        destpath = os.path.join(basepath, destfile)

        fd = file(destpath, 'w')
        fd.write(img_data)
        fd.close()

        self.photograph = destfile
        self.save()

        return
    
    def get_mugshot(self):
        """
        """

        basepath = settings.MEDIA_ROOT
        srcfile =  self.photograph

        if not srcfile:
            return ''

        srcpath = os.path.join(basepath, srcfile)

        return file(srcpath).read()

    
class Speaker(models.Model):
    user = models.ForeignKey(UserProfile, verbose_name = "related user profile", unique = True)
    registered_talks = models.ManyToManyField(Talk, verbose_name = "related talks", blank = True,
                                              null = True)
    def __str__(self):
        return str(self.user)

    class Admin: pass

class Attendee(models.Model):
    user = models.ForeignKey(UserProfile, verbose_name = "related user profile", unique = True)

    def __str__(self):
        return str(self.user)

    class Admin: pass
    
class Room(models.Model):
    name = models.CharField(verbose_name = "room name", maxlength = 50)
    capacity = models.IntegerField(verbose_name = "capacity (people)", default = 1)

    def __str__(self):
        return self.name
    
    class Admin: pass

class Slot(models.Model):
    slot = models.CharField(verbose_name = "title", maxlength = 50)
    t_start = models.TimeField(verbose_name = "Start time")
    t_end = models.TimeField (verbose_name = "End time")

    def __str__(self):
        return self.slot
    
    class Admin: pass
    

class Schedule(models.Model):
    room = models.ForeignKey(Room, verbose_name = "related room", unique = False)
    slot = models.ForeignKey(Slot, verbose_name = "related time slot", unique = False)
    talk = models.ForeignKey(Talk, verbose_name = "related talk", unique = True)

    def __str__(self):
        return str(self.talk) + "/" + str(self.room) + "/" + str(self.slot)

    class Meta:
        unique_together = (("room", "slot", "talk"),)

    class Admin: pass

class Feedback(models.Model):
    sender = models.CharField(verbose_name = "full name", maxlength=50)
    email = models.EmailField(verbose_name = "email address")
    talk = models.ForeignKey(Talk, verbose_name = "related talk", unique = False, blank = True, null = True)
    feedback = models.TextField(verbose_name = "feedback on the talk")

    def __str__(self):
        return self.feedback[:50] + " ..."
    
    class Admin:
        list_display = ('sender', 'email', 'talk', 'feedback')

    class Meta:
        verbose_name_plural = "Feedback"

